[SW Expert Academy] 4112. 피라미드 탐험
Posted on
문제 :
민지가 이상한 피라미드를 발견했다.
이 피라미드는 아래와 같이, 같은 크기의 무수히 많은 원 모양의 방들로 구성되어 있다.
피라미드를 조사하던 중 민지는 보물이 있는 방의 위치를 알아내어 그곳으로 이동하려 한다.
민지는 인접한 방으로만 이동할 수 있으며, 두 방이 인접하려면 두 방 사이에 접점이 존재해야 한다.
예를 들어, 5번 방은 2번, 3번, 4번, 6번, 8번, 9번과는 인접하지만 1번, 7번과는 인접하지 않는다.
또한, 1번 방과 인접한 방은 2번과 3번뿐이다.
1 단위시간에 인접한 한 방으로 이동할 수 있다고 가정하자.
민지와 보물이 있는 방의 위치가 주어질 때, 민지가 보물을 찾을 때까지 걸리는 최소시간을 구하는 프로그램을 작성하시오.
입력 :
첫 번째 줄에 테스트 케이스의 수 T(1 ≤ T ≤ 1,000)가 주어진다.
각 테스트 케이스에 해당하는 줄에는 두 개의 자연수 a, b(1 ≤ a, b ≤ 10,000)가 주어진다. 두 자연수는 각각 민지와 보물이 위치해 있는 방의 번호이다.
출력 :
각 테스트 케이스마다 해당하는 줄에 민지가 보물을 찾아가는데 필요한 최소 단위시간을 출력한다.
풀이 :
처음에는 피라미드 형태를 어떻게 만들어서 탐색해야할지 감이 오지 않았다. 하지만 피라미드 형태의 그림을 계단식 형태 배열로 저장하니 6가지 탐색방향으로 피라미드 맵과 같은 탐색이 가능했다.
사실 본 문제의 경우 피라미드 형태의 방들을 배열에 적합하게 매칭하여 탐색할 수 있게끔 만드는 것을 생각해 내는 것이 키 포인트인 듯 하다. 그 외의 로직은 일반 bfs 방식과 동일하게 6가지 방향으로 방문 여부를 체크하며 탐색을 진해해주면 최소 탐색시간을 구해낼 수 있다.
코드 :
코드 보기/접기
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
typedef struct Qnode {
int x, y, cnt;
}Qnode;
int map[150][150], fin, di[6] = {0, 1, 1, 0, -1, -1}, dj[6] = {1, 1, 0, -1, -1, 0};
bool visit[150][150];
void init() {
int num = 1;
for(int i=1; i<150; i++){
for(int j=1; j<=i; j++) {
map[i][j] = num++;
if(num>10000) return;
}
}
}
int bfs(int stx, int sty) {
memset(visit, false, sizeof(visit));
queue<Qnode> q;
q.push(Qnode{stx, sty, 0});
visit[stx][sty] = true;
while(!q.empty()) {
int curx = q.front().x, cury = q.front().y, curcnt = q.front().cnt;
q.pop();
if(map[curx][cury] == fin) return curcnt;
for(int k=0; k<6; k++) {
int cmpx = curx + di[k], cmpy = cury + dj[k];
if(cmpx < 1 || cmpx >=150 || cmpy < 1 || cmpy >= 150) continue;
if(!map[cmpx][cmpy] || visit[cmpx][cmpy]) continue;
q.push(Qnode{cmpx, cmpy, curcnt + 1});
visit[cmpx][cmpy] = true;
}
}
}
int testCase() {
int start, cmpsum = 0, stx, sty;
cin >> start >> fin;
for(int i=1; i<150; i++) {
cmpsum += i;
if(cmpsum >= start) {
for(int j=1; j<=i; j++)
if(map[i][j] == start) {
stx = i;
sty = j;
break;
}
break;
}
}
return bfs(stx, sty);
}
int main() {
init();
int tc;
cin >> tc;
for(int k=1; k<=tc; k++)
cout << '#' << k << ' ' << testCase() << '\n';
return 0;
}